package cn.king.springframework.aop.aspectj;

import cn.king.springframework.aop.ClassFilter;
import cn.king.springframework.aop.MethodMatcher;
import cn.king.springframework.aop.Pointcut;
import org.aspectj.weaver.tools.PointcutExpression;
import org.aspectj.weaver.tools.PointcutParser;
import org.aspectj.weaver.tools.PointcutPrimitive;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class AspectJExpressionPointcut implements Pointcut,MethodMatcher,ClassFilter{
    /**
     * PointcutPrimitive用于表示一个切点表达式
     */
    private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<PointcutPrimitive>();
    static{
        /**
         * public static final PointcutPrimitive EXECUTION = new PointcutPrimitive("execution", 2);
         */
        SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
    }
    private final PointcutExpression pointcutExpression;

    public AspectJExpressionPointcut(String pointcutExpression) {
        PointcutParser pointcutParser =
                PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
                        SUPPORTED_PRIMITIVES,this.getClass().getClassLoader()
                );
        this.pointcutExpression = pointcutParser.parsePointcutExpression(pointcutExpression);
    }

    @Override
    public ClassFilter getClassFilter() {

        return this;
    }

    @Override
    public MethodMatcher getMatcher() {

        return this;
    }

    /**
     * 匹配类
     * @param clazz
     * @return
     */
    @Override
    public boolean matches(Class<?> clazz) {

        return pointcutExpression.couldMatchJoinPointsInType(clazz);
    }

    /**
     * 匹配方法
     * @param method
     * @param targetClass
     * @return
     */
    @Override
    public boolean matches(Method method, Class<?> targetClass) {

        return pointcutExpression.matchesMethodExecution(method).alwaysMatches();
    }
}
